Android 热敏打印机打印二维码

最近项目需要研究下Android通过usbhost和蓝牙连接热敏打印机打印小票,收集了一下资料参考,感觉这块技术比较乱的,每家打印机都有自己的SDK,但其实底层的原理差不多,做个稳定兼容多个品牌热敏打印机的APP还是有难度的。

  昨天晚上说抽时间来写一篇关于Android 热敏打印机打印二维码和图片的文章,所幸在下班之前把它给写了,和大家分享吧。我的是Android机器有内置热敏打印机的,我是把apk跑在我的Android机器上的,操作程序打印的。
  一、打印机的型号
  RP-POS80S或RP-POS80P或RP-POS80CS或RP-POS80CP打印机 高速热敏打印机  打印方式:直接热敏打印  打印密度:640点/行  打印纸宽:80mm  有效打印宽度:72mm  最小走纸距离:0.125mm  打印字符  ACSII码字符集:12×24点  国标一、二级汉字字库:24×24点  采用命令集:ESC/POS打印命令集
  二、打印位图命令

ESC *m nL nH d1...dk     [名称]   选择位图模式     [格式]   ASCII码   ESC  *       m nL nH d1...dk     十六进制码    1B   2A   m nL nH d1...dk     十进制码   27  42   m nL nH d1...dk     [范围]   m= 0, 1, 32, 33     0 £ nL£ 255     0 £ nH£ 3     0 £ d£ 255

[描述]用 m选择位图的模式,位图的点数由 nL和 nH指定,如下所示:
m 模式垂直方向水平方向点数点密度点密度数据个数 (K)08-点 单密度867.7 dpi101.6 dpinL+ nH´ 25618-点 双密度867.7 dpi203.2 dpinL+ nH´ 2563224-点 单密度24203.2 dpi101.6 dpi(nL+ nH ´ 256) ´33324-点 双密度24203.2 dpi203.2 dpi(nL+ nH ´ 256) ´3
Dpi:每25.4毫米{1英寸}打印点数
[注意]·如果m的值超出了指定的范围,那么nL和之后的数据被当作常规数据处理。· nL和 nH表示水平方向上位图中的点数。通过nL+ nH´ 256计算出点数。· 如果位图数据输入超出了一行上能被打印的点数,那么超出的数据被忽略。· d表示位图数据。设置相应的位为 1去打印某点,或设置为 0以不打印某点。· 如果用GS L 和 GSW 设置的打印范围的宽度比用ESC 命令 发送的数据所要求的宽度小时,则对有问题的行执行下列操作(但是打印不能超出最大可打印范围):
① 打印区域的宽度向右扩展以去适应数据量。② 如果步骤①不能为数据提供足够的宽度,那么左边缘就被减少以去适应数据。对于在单密度模式(m= 0, 32)中的数据的每一位,打印机打印两个点:对于在双密度模式(m= 1, 33)中的数据的每一位,打印机打印一个点。在计算一行中能打印的数据量时,这些必须要考虑。
· 在打印一个位图之后,打印机返回常规数据处理模式。· 这个命令不被打印模式(粗体、重叠、下划线、字符大小、或反白打印)影响, 除非是颠倒打印模式。· 下图描述了图象数据与被打印的点之间的关系。
8-点位图被选定时

三、思路
因为所做的是打印图片(或者是二维码) ,先发送一个请求,从网络下载图片或者是二维码,得到这张图片过后,进行压缩到你想要的大小,在对压缩后的图片进行二值化,即黑白化,但是图片本身会有个α的值(即透明度)的问题,如果不进行处理的话,即使是黑白化的图片,得到图片的像素点也不是很精确。对于去透明度处理过后,在对这张图的每个最标点去像素值,即xxx X xxx大的图片,会有xxx X xxx个像素点。求出每个像素点的r、g、b的值,通过换算公式进行换算,得到一个像素值(0-255之间)。如果是0-128是黑色,129-255是白色(非黑即白化),这样每个点的像素值就可以确定了。
因为我的热敏打印机是24
24的,所以会是24个像素点为一组,假设我把图片压缩为360360像素的大小,就会有15组(纵向的15行,横坐标还是360)。一组的有24360的像素点,因为8位是一个字节,这样24个像素点可以分为3组,每8位组成一个字节,每个像素点不是0就是1(之前已经非黑即白过),这样会得到一个byte数组,如:byte[] b1 = {1, 0, 0, 1, 0, 0, 0, 1}; 在将这样的数组换成十进制的数值int v1;这样就会得到315360个的int 值,在将这些int的值和打印机的打印头命令拼接起来,组成一个byte[] 数组,就可以打印了。
四、注意
1.热敏打印机是一行一行的打印,所以每一行又得加上打印的头命令,我的打印机头命令是5个,所以byte[]数组的长度会是315360+515
2.大家看好自己打印机的打印密度,比如我的是24
24的,所以我剪裁图片的大小会是24的倍数,360*360.大家最好也剪裁成相应的倍数,这样计算会方便点,不然的话,要对空白区域进行白色补缺。
贴代码1. package com.woyou.util;

  1. import android.graphics.Bitmap;

  2. import android.graphics.Canvas;

  3. import android.graphics.Matrix;

  4. import android.graphics.Rect;

  5. import android.util.Log;

  6. /**

    • 将图片转化为二进制
    • @author nsz
    • 2015年1月30日
  7. */

  8. public class PicFromPrintUtils {

  9. public void init(){

  10. // Gray = 0.29900 R + 0.58700 G + 0.11400 * B

  11. }

  12. /*

    • 我们的热敏打印机是RP-POS80S或RP-POS80P或RP-POS80CS或RP-POS80CP打印机
    • 360*360的图片,8个字节(8个像素点)是一个二进制,将二进制转化为十进制数值
    • y轴:24个像素点为一组,即360就是15组(0-14)
    • x轴:360个像素点(0-359)
    • 里面的每一组(24360),每8个像素点为一个二进制,(每组有3个,38=24)
  13. **/

  14. /**

    • 把一张Bitmap图片转化为打印机可以打印的bit(将图片压缩为360*360)
    • 效率很高(相对于下面)
    • @param bit
    • @return
  15. */

  16. public static byte[] draw2PxPoint(Bitmap bit) {

  17. byte[] data = new byte[16290];

  18. int k = 0;

  19. for (int j = 0; j < 15; j++) {

  20. data[k++] = 0x1B;

  21. data[k++] = 0x2A;

  22. data[k++] = 33; // m=33时,选择24点双密度打印,分辨率达到200DPI。

  23. data[k++] = 0x68;

  24. data[k++] = 0x01;

  25. for (int i = 0; i < 360; i++) {

  26. for (int m = 0; m < 3; m++) {

  27. for (int n = 0; n < 8; n++) {

  28. byte b = px2Byte(i, j 24 + m 8 + n, bit);

  29. data[k] += data[k] + b;

  30. }

  31. k++;

  32. }

  33. }

  34. data[k++] = 10;

  35. }

  36. return data;

  37. }

  38. /**

    • 把一张Bitmap图片转化为打印机可以打印的bit
    • @param bit
    • @return
  39. */

  40. public static byte[] pic2PxPoint(Bitmap bit){

  41. long start = System.currentTimeMillis();

  42. byte[] data = new byte[16290];

  43. int k = 0;

  44. for (int i = 0; i < 15; i++) {

  45. data[k++] = 0x1B;

  46. data[k++] = 0x2A;

  47. data[k++] = 33; // m=33时,选择24点双密度打印,分辨率达到200DPI。

  48. data[k++] = 0x68;

  49. data[k++] = 0x01;

  50. for (int x = 0; x < 360; x++) {

  51. for (int m = 0; m < 3; m++) {

  52. byte[] by = new byte[8];

  53. for (int n = 0; n < 8; n++) {

  54. byte b = px2Byte(x, i 24 + m 8 +7-n, bit);

  55. by[n] = b;

  56. }

  57. data[k] = (byte) changePointPx1(by);

  58. k++;

  59. }

  60. }

  61. data[k++] = 10;

  62. }

  63. long end = System.currentTimeMillis();

  64. long str = end - start;

  65. Log.i(“TAG”, “str:” + str);

  66. return data;

  67. }

  68. /**

    • 图片二值化,黑色是1,白色是0
    • @param x 横坐标
    • @param y 纵坐标
    • @param bit 位图
    • @return
  69. */

  70. public static byte px2Byte(int x, int y, Bitmap bit) {

  71. byte b;

  72. int pixel = bit.getPixel(x, y);

  73. int red = (pixel & 0x00ff0000) >> 16; // 取高两位

  74. int green = (pixel & 0x0000ff00) >> 8; // 取中两位

  75. int blue = pixel & 0x000000ff; // 取低两位

  76. int gray = RGB2Gray(red, green, blue);

  77. if ( gray < 128 ){

  78. b = 1;

  79. } else {

  80. b = 0;

  81. }

  82. return b;

  83. }

  84. /**

    • 图片灰度的转化
    • @param r
    • @param g
    • @param b
    • @return
  85. */

  86. private static int RGB2Gray(int r, int g, int b){

  87. int gray = (int) (0.29900 r + 0.58700 g + 0.11400 * b); //灰度转化公式

  88. return gray;

  89. }

  90. /**

    • 对图片进行压缩(去除透明度)
    • @param bitmapOrg
  91. */

  92. public static Bitmap compressPic(Bitmap bitmapOrg) {

  93. // 获取这个图片的宽和高

  94. int width = bitmapOrg.getWidth();

  95. int height = bitmapOrg.getHeight();

  96. // 定义预转换成的图片的宽度和高度

  97. int newWidth = 360;

  98. int newHeight = 360;

  99. Bitmap targetBmp = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

  100. Canvas targetCanvas = new Canvas(targetBmp);

  101. targetCanvas.drawColor(0xffffffff);

  102. targetCanvas.drawBitmap(bitmapOrg, new Rect(0, 0, width, height), new Rect(0, 0, newWidth, newHeight), null);

  103. return targetBmp;

  104. }

  105. /**

    • 对图片进行压缩(不去除透明度)
    • @param bitmapOrg
  106. */

  107. public static Bitmap compressBitmap(Bitmap bitmapOrg) {

  108. // 加载需要操作的图片,这里是一张图片

  109. // Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),R.drawable.alipay);

  110. // 获取这个图片的宽和高

  111. int width = bitmapOrg.getWidth();

  112. int height = bitmapOrg.getHeight();

  113. // 定义预转换成的图片的宽度和高度

  114. int newWidth = 360;

  115. int newHeight = 360;

  116. // 计算缩放率,新尺寸除原始尺寸

  117. float scaleWidth = ((float) newWidth) / width;

  118. float scaleHeight = ((float) newHeight) / height;

  119. // 创建操作图片用的matrix对象

  120. Matrix matrix = new Matrix();

  121. // 缩放图片动作

  122. matrix.postScale(scaleWidth, scaleHeight);

  123. // 创建新的图片

  124. Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width,height, matrix, true);

  125. // 将上面创建的Bitmap转换成Drawable对象,使得其可以使用在ImageView, ImageButton中

  126. // BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);

  127. return resizedBitmap;

  128. }

  129. /**

    • 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值(效率更高)
    • @param arry
    • @return
  130. */

  131. public static int changePointPx1(byte[] arry){

  132. int v = 0;

  133. for (int j = 0; j <arry.length; j++) {

  134. if( arry[j] == 1) {

  135. v = v | 1 << j;

  136. }

  137. }

  138. return v;

  139. }

  140. /**

    • 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值
    • @param arry
    • @return
  141. */

  142. public byte changePointPx(byte[] arry){

  143. byte v = 0;

  144. for (int i = 0; i < 8; i++) {

  145. v += v + arry[i];

  146. }

  147. return v;

  148. }

  149. /**

    • 得到位图的某个点的像素值
    • @param bitmap
    • @return
  150. */

  151. public byte[] getPicPx(Bitmap bitmap){

  152. int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];// 保存所有的像素的数组,图片宽×高

  153. bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());

  154. for (int i = 0; i < pixels.length; i++) {

  155. int clr = pixels[i];

  156. int red = (clr & 0x00ff0000) >> 16; // 取高两位

  157. int green = (clr & 0x0000ff00) >> 8; // 取中两位

  158. int blue = clr & 0x000000ff; // 取低两位

  159. System.out.println(“r=” + red + “,g=” + green + “,b=” + blue);

  160. }

  161. return null;

  162. }

  163. }

复制代码
下面楼层继续…

  1. package com.woyou.util;

  2. import java.io.ByteArrayOutputStream;

  3. import java.io.File;

  4. import java.io.IOException;

  5. import java.io.InputStream;

  6. import java.io.OutputStream;

  7. import java.security.InvalidParameterException;

  8. import java.text.DecimalFormat;

  9. import java.text.SimpleDateFormat;

  10. import java.util.Date;

  11. import java.util.Locale;

  12. import android.content.Context;

  13. import android_serialport_api.SerialPort;

  14. /**

    • 打印机辅助
    • @author nsz 2015年1月30日
  15. */

  16. public class PrintUtil {

  17. final static int BUFFER_SIZE = 4096;

  18. /**

    • 对一个byte[] 进行打印
    • @param printText
    • @return
    • add by yidie
  19. */

  20. public static boolean printBytes(byte[] printText) {

  21. boolean returnValue = true;

  22. try {

  23. OutputStream mOutputStream = getSerialPort().getOutputStream();

  24. mOutputStream.write(printText);

  25. } catch (Exception ex) {

  26. returnValue = false;

  27. }

  28. return returnValue;

  29. }

  30. /**

    • “\n” 就是换行
    • @param paramString
    • @return
    • add by yidie
  31. */

  32. public static boolean printString(String paramString) {

  33. return printBytes(getGbk(paramString));

  34. }

  35. /*

    • add by yidie 2012-01-10 功能:设置打印绝对位置 参数: int 在当前行,定位光标位置,取值范围0至576点 说明:
    • 在字体常规大小下,每汉字24点,英文字符12点 如位于第n个汉字后,则position=24*n
    • 如位于第n个半角字符后,则position=12*n
  36. **/

  37. public static byte[] setCusorPosition(int position) {

  38. byte[] returnText = new byte[4]; // 当前行,设置绝对打印位置 ESC $ bL bH

  39. returnText[0] = 0x1B;

  40. returnText[1] = 0x24;

  41. returnText[2] = (byte) (position % 256);

  42. returnText[3] = (byte) (position / 256);

  43. return returnText;

  44. }

  45. /**

    • 设置打印机的行高
    • @param h
    • @return
  46. */

  47. public static byte[] setLineHeight(byte h) {

  48. byte[] returnText = new byte[] { 0x1B, 0x33, h }; // 切纸; 1B 33 n

  49. return returnText;

  50. }

  51. public static byte[] setDefaultLineHeight() {

  52. byte[] returnText = new byte[] { 0x1B, 0x32 }; // 切纸; 1B 32

  53. return returnText;

  54. }

  55. public static byte[] InputStreamTOByte(InputStream in) throws IOException {

  56. ByteArrayOutputStream outStream = new ByteArrayOutputStream();

  57. byte[] data = new byte[BUFFER_SIZE];

  58. int count = -1;

  59. while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)

  60. outStream.write(data, 0, count);

  61. data = null;

  62. return outStream.toByteArray();

  63. }

  64. /**

    • 打印我有外卖的logo
    • @param c
  65. */

  66. public static void printLogo(Context c) {

  67. PrintUtil.printBytes(PrintUtil.setLineHeight((byte) 0));

  68. InputStream is = c.getClass().getResourceAsStream(“/assets/bill.bin”);

  69. byte[] b;

  70. try {

  71. b = InputStreamTOByte(is);

  72. PrintUtil.printBytes(b);

  73. PrintUtil.printBytes(PrintUtil.setDefaultLineHeight());

  74. } catch (Exception e) {

  75. e.printStackTrace();

  76. }

  77. }

  78. public static byte[] getLogo(Context c) {

  79. InputStream is = c.getClass().getResourceAsStream(“/assets/bill.bin”);

  80. byte[] b;

  81. try {

  82. b = InputStreamTOByte(is);

  83. return b;

  84. } catch (Exception e) {

  85. e.printStackTrace();

  86. }

  87. return null;

  88. }

  89. /**

    • 得到店铺logo
    • @param c
    • @param bit
    • @return
  90. */

  91. public static byte[] getLogo(Context c, byte[] bit) {

  92. InputStream is = c.getClass().getResourceAsStream(“/assets/bill.bin”);

  93. byte[] b = bit;

  94. try {

  95. b = InputStreamTOByte(is);

  96. return b;

  97. } catch (Exception e) {

  98. e.printStackTrace();

  99. }

  100. return null;

  101. }

  102. public static byte[] getLogo(byte[] bs) {

  103. byte[] b;

  104. try {

  105. b = bs;

  106. return b;

  107. } catch (Exception e) {

  108. e.printStackTrace();

  109. }

  110. return null;

  111. }

  112. /**

    • 支付打印(二维码)
    • @param b
    • @param money
    • @return
    • [url=home.php?mod=space&uid=2643633]@throws[/url] InvalidParameterException
    • @throws SecurityException
    • @throws IOException
  113. */

  114. public static boolean printAlipayTitle(byte[] b, String money)

  115. throws InvalidParameterException, SecurityException, IOException {

  116. int iNum = 0;

  117. byte[] tempBuffer = new byte[1000];

  118. byte[] oldText = setAlignCenter(‘2’);

  119. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  120. iNum += oldText.length;

  121. oldText = setWH(‘4’);

  122. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  123. iNum += oldText.length;

  124. oldText = setBold(true);

  125. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  126. iNum += oldText.length;

  127. oldText = getGbk(“支付凭证\n”);

  128. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  129. iNum += oldText.length;

  130. oldText = getGbk(“\n”);

  131. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  132. iNum += oldText.length;

  133. oldText = setAlignCenter(‘2’);

  134. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  135. iNum += oldText.length;

  136. oldText = setWH(‘3’);

  137. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  138. iNum += oldText.length;

  139. oldText = setBold(true);

  140. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  141. iNum += oldText.length;

  142. oldText = getGbk(“您共消费了” + money + “元\n”);

  143. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  144. iNum += oldText.length;

  145. oldText = getGbk(“\n”);

  146. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  147. iNum += oldText.length;

  148. oldText = setAlignCenter(‘2’);

  149. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  150. iNum += oldText.length;

  151. oldText = setWH(‘3’);

  152. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  153. iNum += oldText.length;

  154. oldText = setBold(true);

  155. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  156. iNum += oldText.length;

  157. oldText = getGbk(“请扫码支付\n\n”);

  158. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  159. iNum += oldText.length;

  160. SerialPort mSerialPort = getSerialPort();

  161. OutputStream mOutputStream = mSerialPort.getOutputStream();

  162. try {

  163. mOutputStream.write(tempBuffer);

  164. printBytes(b);

  165. printString(“\n\n\n”);

  166. printBytes(CutPaper());

  167. } catch (IOException e) {

  168. e.printStackTrace();

  169. return false;

  170. }

  171. return true;

  172. }

  173. /*

    • add by yidie 2012-01-10 功能:订单打印 参数: String 订单短号 OrderDetail 打印内容,包含
    • GoodsInfo[] String 打印标题
  174. **/

  175. public static boolean printOrder(Context c, byte[] b)

  176. throws InvalidParameterException, SecurityException, IOException {

  177. DecimalFormat dcmFmt = new DecimalFormat(“0.00”);

  178. int iNum = 0, i;

  179. byte[] tempBuffer = new byte[8000];

  180. String stTmp = “”;

  181. byte[] oldText = setAlignCenter(‘2’);

  182. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  183. iNum += oldText.length;

  184. oldText = getLogo(c, b);

  185. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  186. iNum += oldText.length;

  187. oldText = setWH(‘1’);

  188. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  189. iNum += oldText.length;

  190. oldText = getGbk(“\n”);

  191. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  192. iNum += oldText.length;

  193. oldText = setAlignCenter(‘2’);

  194. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  195. iNum += oldText.length;

  196. oldText = setWH(‘4’);

  197. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  198. iNum += oldText.length;

  199. oldText = setBold(true);

  200. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  201. iNum += oldText.length;

  202. oldText = setWH(‘1’);

  203. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  204. iNum += oldText.length;

  205. oldText = getGbk(“\n”);

  206. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  207. iNum += oldText.length;

  208. oldText = setAlignCenter(‘1’);

  209. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  210. iNum += oldText.length;

  211. oldText = setCusorPosition(324);

  212. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  213. iNum += oldText.length;

  214. String strTime = new SimpleDateFormat(“yyyy-MM-dd HH:mm”,

  215. Locale.SIMPLIFIED_CHINESE).format(new Date());

  216. oldText = getGbk(strTime + “打印\n”);

  217. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  218. iNum += oldText.length;

  219. oldText = setBold(false);

  220. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  221. iNum += oldText.length;

  222. oldText = getGbk(“———————————————-\n”);

  223. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  224. iNum += oldText.length;

  225. oldText = setWH(‘3’);

  226. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  227. iNum += oldText.length;

  228. oldText = getGbk(“ 商品名称 单价 数量 金额\n”);

  229. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  230. iNum += oldText.length;

  231. oldText = getGbk(“———————————————-\n”);

  232. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  233. iNum += oldText.length;

  234. oldText = setWH(‘3’);

  235. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  236. iNum += oldText.length;

  237. oldText = setAlignCenter(‘2’);

  238. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  239. iNum += oldText.length;

  240. oldText = setWH(‘1’);

  241. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  242. iNum += oldText.length;

  243. oldText = getGbk(“\n感谢使用[我有外卖]订餐,24小时服务热线 4008519517\n\n\n”);

  244. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  245. iNum += oldText.length;

  246. oldText = CutPaper();

  247. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  248. iNum += oldText.length;

  249. SerialPort mSerialPort = getSerialPort();

  250. OutputStream mOutputStream = mSerialPort.getOutputStream();

  251. try {

  252. mOutputStream.write(tempBuffer);

  253. } catch (IOException e) {

  254. e.printStackTrace();

  255. return false;

  256. }

  257. return true;

  258. }

  259. /*

    • add by yidie 2012-01-12 功能:报表打印 参数: String 打印标题,如“月报表:2013-01”
    • ReportUserSale 打印内容,包含 UserSaleInfo[]
  260. **/

  261. public static boolean printReportUser() throws InvalidParameterException,

  262. SecurityException, IOException {

  263. int iNum = 0;

  264. String stTmp = “”;

  265. byte[] tempBuffer = new byte[8000];

  266. SerialPort mSerialPort = getSerialPort();

  267. OutputStream mOutputStream = mSerialPort.getOutputStream();

  268. byte[] oldText = setAlignCenter(‘1’);

  269. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  270. iNum += oldText.length;

  271. oldText = setWH(‘3’);

  272. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  273. iNum += oldText.length;

  274. oldText = setCusorPosition(324);

  275. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  276. iNum += oldText.length;

  277. String strTime = new SimpleDateFormat(“yyyy-MM-dd HH:mm”,

  278. Locale.SIMPLIFIED_CHINESE).format(new Date());

  279. oldText = getGbk(strTime + “打印\n”);

  280. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  281. iNum += oldText.length;

  282. oldText = setWH(‘1’);

  283. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  284. iNum += oldText.length;

  285. oldText = setAlignCenter(‘2’);

  286. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  287. iNum += oldText.length;

  288. oldText = setWH(‘4’);

  289. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  290. iNum += oldText.length;

  291. oldText = setBold(true);

  292. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  293. iNum += oldText.length;

  294. oldText = setWH(‘1’);

  295. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  296. iNum += oldText.length;

  297. oldText = getGbk(“\n\n”);

  298. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  299. iNum += oldText.length;

  300. oldText = setAlignCenter(‘1’);

  301. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  302. iNum += oldText.length;

  303. oldText = setBold(false);

  304. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  305. iNum += oldText.length;

  306. oldText = setWH(‘1’);

  307. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  308. iNum += oldText.length;

  309. oldText = getGbk(“   用户        售出数量 售出金额\n”);

  310. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  311. iNum += oldText.length;

  312. oldText = getGbk(“———————————————-\n”);

  313. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  314. iNum += oldText.length;

  315. oldText = CutPaper();

  316. System.arraycopy(oldText, 0, tempBuffer, iNum, oldText.length);

  317. iNum += oldText.length;

  318. try {

  319. mOutputStream.write(tempBuffer);

  320. } catch (IOException e) {

  321. e.printStackTrace();

  322. return false;

  323. }

  324. return true;

  325. }

  326. /*

    • add by yidie 2012-01-12 功能:报表打印 参数: String 打印标题,如“月报表:2013-01” ReportSale
    • 打印内容,包含 SaleInfo[]
  327. **/

  328. private static SerialPort mSerialPort = null;

  329. public static SerialPort getSerialPort() throws SecurityException,

  330. IOException, InvalidParameterException {

  331. if (mSerialPort == null) {

  332. String spFile = null;

  333. String model = MainBoardUtil.getModel(); // android.os.Build.MODEL.toLowerCase();

  334. if (model.contains(Constants.MAIN_BOARD_SMDKV210)) {

  335. spFile = “/dev/s3c2410_serial0”;

  336. } else if (model.contains(Constants.MAIN_BOARD_RK30)) {

  337. spFile = “/dev/ttyS1”;

  338. } else if (model.contains(Constants.MAIN_BOARD_C500)) {

  339. spFile = “/dev/ttyS1”;

  340. } else {

  341. throw new IOException(“unknow hardware!”);

  342. }

  343. int baudrate = 115200;

  344. boolean flagCon = true;

  345. File myFile = new File(spFile);

  346. / Open the serial port /

  347. mSerialPort = new SerialPort(myFile, baudrate, 0, flagCon);

  348. }

  349. return mSerialPort;

  350. }

  351. public static void closeSerialPort() {

  352. if (mSerialPort != null) {

  353. mSerialPort.close();

  354. mSerialPort = null;

  355. }

  356. }

  357. public static byte[] getGbk(String stText) {

  358. byte[] returnText = null;

  359. try {

  360. returnText = stText.getBytes(“GBK”); // 必须放在try内才可以

  361. } catch (Exception ex) {

  362. ;

  363. }

  364. return returnText;

  365. }

  366. public static byte[] setWH(char dist) {

  367. byte[] returnText = new byte[3]; // GS ! 11H 倍宽倍高

  368. returnText[0] = 0x1D;

  369. returnText[1] = 0x21;

  370. switch (dist) // 1-无;2-倍宽;3-倍高; 4-倍宽倍高

  371. {

  372. case ‘2’:

  373. returnText[2] = 0x10;

  374. break;

  375. case ‘3’:

  376. returnText[2] = 0x01;

  377. break;

  378. case ‘4’:

  379. returnText[2] = 0x11;

  380. break;

  381. default:

  382. returnText[2] = 0x00;

  383. break;

  384. }

  385. return returnText;

  386. }

  387. /**

    • 打印的对齐方式
    • @param dist
    • @return
  388. */

  389. public static byte[] setAlignCenter(char dist) {

  390. byte[] returnText = new byte[3]; // 对齐 ESC a

  391. returnText[0] = 0x1B;

  392. returnText[1] = 0x61;

  393. switch (dist) // 1-左对齐;2-居中对齐;3-右对齐

  394. {

  395. case ‘2’:

  396. returnText[2] = 0x01;

  397. break;

  398. case ‘3’:

  399. returnText[2] = 0x02;

  400. break;

  401. default:

  402. returnText[2] = 0x00;

  403. break;

  404. }

  405. return returnText;

  406. }

  407. public static byte[] setBold(boolean dist) {

  408. byte[] returnText = new byte[3]; // 加粗 ESC E

  409. returnText[0] = 0x1B;

  410. returnText[1] = 0x45;

  411. if (dist) {

  412. returnText[2] = 0x01; // 表示加粗

  413. } else {

  414. returnText[2] = 0x00;

  415. }

  416. return returnText;

  417. }

  418. public static byte[] PrintBarcode(String stBarcode) {

  419. int iLength = stBarcode.length() + 4;

  420. byte[] returnText = new byte[iLength];

  421. returnText[0] = 0x1D;

  422. returnText[1] = ‘k’;

  423. returnText[2] = 0x45;

  424. returnText[3] = (byte) stBarcode.length(); // 条码长度;

  425. System.arraycopy(stBarcode.getBytes(), 0, returnText, 4,

  426. stBarcode.getBytes().length);

  427. return returnText;

  428. }

  429. /**

    • 切纸
    • @return
  430. */

  431. public static byte[] CutPaper() {

  432. byte[] returnText = new byte[] { 0x1D, 0x56, 0x42, 0x00 }; // 切纸; GS V

  433. // 66D 0D

  434. return returnText;

  435. }

  436. }

复制代码1. package com.woyou.woyoupay;

  1. import java.io.IOException;

  2. import java.net.URL;

  3. import java.util.ArrayList;

  4. import java.util.List;

  5. import org.json.JSONException;

  6. import org.json.JSONObject;

  7. import android.app.Activity;

  8. import android.app.ProgressDialog;

  9. import android.content.Intent;

  10. import android.graphics.Bitmap;

  11. import android.graphics.BitmapFactory;

  12. import android.graphics.drawable.Drawable;

  13. import android.os.Bundle;

  14. import android.text.Html;

  15. import android.util.Log;

  16. import android.view.View;

  17. import android.view.View.OnClickListener;

  18. import android.view.Window;

  19. import android.widget.ImageView;

  20. import android.widget.TextView;

  21. import com.anjoyo.net.AsyncHttpClient;

  22. import com.anjoyo.net.JsonHttpResponseHandler;

  23. import com.anjoyo.net.RequestParams;

  24. import com.woyou.R;

  25. import com.woyou.bean.ScanCodeRes;

  26. import com.woyou.util.Constants;

  27. import com.woyou.util.PicFromPrintUtils;

  28. import com.woyou.util.PrintUtil;

  29. import com.woyou.util.ThreadPoolManager;

  30. public class Print2DCodeAct extends Activity implements OnClickListener {

  31. private static final String TAG = “Print2DCodeAct”;

  32. TextView back, print, motifiscan;

  33. TextView oId, money, price;

  34. ImageView printImg;

  35. ProgressDialog dialog;

  36. @Override

  37. protected void onCreate(Bundle savedInstanceState) {

  38. super.onCreate(savedInstanceState);

  39. requestWindowFeature(Window.FEATURE_NO_TITLE);

  40. setContentView(R.layout.activity_print2dcode);

  41. initView();

  42. }

  43. String extra;

  44. private void initView() {

  45. Intent intent = getIntent();

  46. extra = intent.getStringExtra(“money”);

  47. back = (TextView) this.findViewById(R.id.back);

  48. oId = (TextView) this.findViewById(R.id.order_id);

  49. back.setOnClickListener(this);

  50. motifiscan = (TextView) this.findViewById(R.id.motifiscan);

  51. print = (TextView) this.findViewById(R.id.print_image);

  52. printImg = (ImageView) this.findViewById(R.id.print_two_image);

  53. money = (TextView) this.findViewById(R.id.money);

  54. print.setOnClickListener(this);

  55. motifiscan.setOnClickListener(this);

  56. money.setText(Html.fromHtml(“¥“ + extra + ““));

  57. //显示图片

  58. // Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(), R.drawable.alipay);

  59. // Bitmap bitmap = compressPic(bitmapOrg);

  60. // image_alipy.setImageBitmap(bitmap);

  61. //请求数据

  62. getData();

  63. }

  64. private void showDialog() {

  65. if (dialog == null) {

  66. dialog = new ProgressDialog(this);

  67. dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

  68. dialog.setCancelable(true);

  69. dialog.setMessage(“正在加载中,请稍候…”);

  70. }

  71. dialog.show();

  72. }

  73. private void hideDialog() {

  74. runOnUiThread(new Runnable() {

  75. @Override

  76. public void run() {

  77. if (dialog != null) {

  78. dialog.dismiss();

  79. }

  80. }

  81. });

  82. }

  83. @Override

  84. protected void onResume() {

  85. super.onResume();

  86. Constants.ACTIVITY_INSTANCE = Print2DCodeAct.this;

  87. }

  88. List list = new ArrayList();

  89. Bitmap compressPic = null;

  90. String big_pic_url;

  91. String pic_url;

  92. String small_pic_url;

  93. private void getData() {

  94. float f = Float.parseFloat(extra) * 100;

  95. int inte = (int) f;

  96. long parseLong = Long.parseLong(String.valueOf(inte));

  97. String sign = Constants.md5(“100512354” + “150039203” + Constants.KEY);

  98. String url = “http://api.coupon.dev.wosai.cn/Upay/alipayQrCodeOffline“;

  99. AsyncHttpClient client = new AsyncHttpClient();

  100. RequestParams params = new RequestParams();

  101. params.put(“store_own_order_id”, “1234”);

  102. params.put(“subject”, “喔噻体验商品”);

  103. params.put(“total_fee”, parseLong+””);

  104. params.put(“wosai_store_id”, “100512354”);

  105. params.put(“wosai_app_id”, “150039203”);

  106. params.put(“sign”, sign);

  107. params.put(“notify_url”, “http://www.woyouwaimai.com/get“); //推送支付成功的通知

  108. Log.i(TAG, url + params);

  109. client.get(url, params, new JsonHttpResponseHandler() {

  110. @Override

  111. public void onStart() {

  112. super.onStart();

  113. showDialog();

  114. }

  115. @Override

  116. public void onSuccess(JSONObject response) {

  117. super.onSuccess(response);

  118. try {

  119. String code = response.getString(“code”);

  120. String msg = response.getString(“msg”);

  121. Log.i(TAG, “code:” + code);

  122. Log.i(TAG, “msg:” + msg);

  123. if (“10000”.equals(code)) {

  124. JSONObject data = response.getJSONObject(“data”);

  125. String order_sn = data.getString(“order_sn”);

  126. String wosai_store_id = data.getString(“wosai_store_id”);

  127. int status = data.getInt(“status”);

  128. String ctime = data.getString(“ctime”);

  129. JSONObject order_pay_detail = data.getJSONObject(“order_pay_detail”);

  130. String order_detail = data.getString(“order_detail”);

  131. String pay_way = data.getString(“pay_way”);

  132. long total_fee = data.getLong(“total_fee”);

  133. String is_success = order_pay_detail.getString(“is_success”);

  134. JSONObject responses = order_pay_detail.getJSONObject(“response”);

  135. String sign = order_pay_detail.getString(“sign”);

  136. String sign_type = order_pay_detail.getString(“sign_type”);

  137. JSONObject alipay = responses.getJSONObject(“alipay”);

  138. big_pic_url = alipay.getString(“big_pic_url”);

  139. String out_trade_no = alipay.getString(“out_trade_no”);

  140. pic_url = alipay.getString(“pic_url”);

  141. String qr_code = alipay.getString(“qr_code”);

  142. String result_code = alipay.getString(“result_code”);

  143. small_pic_url = alipay.getString(“small_pic_url”);

  144. String voucher_type = alipay.getString(“voucher_type”);

  145. Log.i(TAG, “big_pic_url:” + big_pic_url);

  146. Log.i(TAG, “pic_url:” + pic_url);

  147. Log.i(TAG, “small_pic_url:” + small_pic_url);

  148. ScanCodeRes res = new ScanCodeRes();

  149. res.setOrder_sn(order_sn);

  150. res.setWosai_store_id(wosai_store_id);

  151. res.setStatus(status);

  152. res.setCtime(ctime);

  153. res.setIs_success(is_success);

  154. res.setOrder_detail(order_detail);

  155. res.setTotal_fee(total_fee);

  156. res.setPay_way(pay_way);

  157. list.add(res);

  158. Constants.memoryCache.put(Constants.SCAN_CODE_RESULT, list);

  159. }

  160. } catch (JSONException e) {

  161. e.printStackTrace();

  162. hideDialog();

  163. }

  164. }

  165. @Override

  166. public void onFinish() {

  167. super.onFinish();

  168. ThreadPoolManager.getInstance().executeTask(new Runnable() {

  169. @Override

  170. public void run() {

  171. try {

  172. Bitmap bitmap = BitmapFactory.decodeStream(new URL(pic_url).openStream());

  173. compressPic = PicFromPrintUtils.compressPic(bitmap);

  174. }catch (IOException e) {

  175. e.printStackTrace();

  176. }

  177. runOnUiThread(new Runnable() {

  178. @Override

  179. public void run() {

  180. printImg.setImageBitmap(compressPic);

  181. print2Code(compressPic);

  182. hideDialog();

  183. }

  184. });

  185. }

  186. });

  187. }

  188. });

  189. }

  190. //打印二维码

  191. private void print2Code(Bitmap bitmap){

  192. final byte[] bs = PicFromPrintUtils.draw2PxPoint(bitmap);

  193. ThreadPoolManager.getInstance().executeTask(new Runnable() {

  194. @Override

  195. public void run() {

  196. try {

  197. PrintUtil.printAlipayTitle(bs, extra);

  198. } catch (Exception e) {

  199. e.printStackTrace();

  200. }

  201. }

  202. });

  203. }

  204. @Override

  205. public void onClick(View v) {

  206. switch (v.getId()) {

  207. case R.id.print_image:

  208. if ( compressPic != null ){

  209. print2Code(compressPic);

  210. }

  211. break;

  212. case R.id.back:

  213. finish();

  214. break;

  215. case R.id.motifiscan:

  216. Intent intent = new Intent(this, HomeAct.class);

  217. intent.putExtra(“money”, extra);

  218. startActivity(intent);

  219. break;

  220. }

  221. }

  222. public Drawable loadImageFromNetwork(String urladdr) {

  223. Drawable drawable = null;

  224. try {

  225. drawable = Drawable.createFromStream(new URL(urladdr).openStream(),”image.jpg”);

  226. } catch (IOException e) {

  227. Log.d(“test”, e.getMessage());

  228. }

  229. if (drawable == null) {

  230. Log.d(“test”, “null drawable”);

  231. } else {

  232. Log.d(“test”, “not null drawable”);

  233. }

  234. return drawable;

  235. }

  236. // 计算图片的缩放值

  237. public static int calculateInSampleSize(BitmapFactory.Options options,

  238. int reqWidth, int reqHeight) {

  239. final int height = options.outHeight;

  240. final int width = options.outWidth;

  241. int inSampleSize = 1;

  242. if (height > reqHeight || width > reqWidth) {

  243. final int heightRatio = Math.round((float) height

  244. / (float) reqHeight);

  245. final int widthRatio = Math.round((float) width / (float) reqWidth);

  246. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

  247. }

  248. return inSampleSize;

  249. }

  250. }

复制代码

代码不是很全,只上了一些核心的代码,因为这是公司的项目,不适合把工程贴上来,忘大家见谅。中间会有一些简单的算法,是为提高效率用的,代码的整合力度也不是很好,大家将就点吧。

原文
http://www.eoeandroid.com/thread-564903-1-1.html?_dsign=50a25db8

Contents
,